Матч 363, Пожатие рук (HandsShaking)

Дивизион 2, Уровень 2; Дивизион 1, Уровень 1

 

За круглым столом собрались p бизнесменов. Перед совещанием они должны одновременно пожать друг другу руки. Руки никаких бизнесменов не должны пересекаться. Выяснить, сколькими способами они могут пожать руки друг другу, если p четно.

 

Класс: HandsShaking

Метод: long long countPerfect(int p)

Ограничения: 2 £ p £ 50, p четное.

 

Вход. Целое четное число p.

 

Выход. Количество способов, которыми бизнесмены могут пожать друг другу руки.

 

Пример входа

p

2

4

8

 

Пример выхода

1

2

14

 

РЕШЕНИЕ

числа Каталана

 

Пронумеруем бизнесменов, сидящих за столом, числами 1, 2, ..., 2*n = p. Обозначим через f(n) количество способов, которыми они могут пожать друг другу руки согласно условию задачи. Рассмотрим все возможные рукопожатия первого бизнесмена. Он может протянуть руку только тому бизнесмену, который имеет четный номер. Если первый бизнесмен протягивает руку (2 * k) - ому, то с одной стороны пересечения их рук останется 2 * k – 2 людей, которые могут пожать руки f(k – 1) способами, а с другой стороны 2 * n – 2 * k людей, которые могут пожать руки f(nk) способами. Выбирая k = 1, 2, …, n, получим:

f(n) = f(0) * f(n – 1) + f(1) * f(n – 2) + … + f(k – 1) * f(nk) + … + f(n – 1) * f(0),

f(1) = 1, f(0) = 1

То есть f(n) = являются числами Каталана.

Ответом на задачу будет значение f(p/2).

Значения чисел Каталана вычисляем в массиве cat по приведенной выше формуле:

n

0

1

2

3

4

5

6

7

8

9

10

f(n)

1

1

2

5

14

42

132

429

1430

4862

16796

 

 

ПРОГРАММА

 

#include <stdio.h>

 

long long cat[51];

 

class HandsShaking

{

public:

  long long countPerfect(int n)

  {

    int i, j;

    cat[0] = cat[1] = 1;

    for(i = 2; i <= n; i++)

      for(j = 0; j < i; j++)

        cat[i] += cat[j] * cat[i - j - 1];

    return cat[n/2];

  }

};